package com.tlgen.orm.utils.xml;

import cn.hutool.core.util.StrUtil;
import com.tlgen.orm.components.sqlXml.XmlConfigManager;
import com.tlgen.orm.utils.log.TraceLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
public class SqlXmlLoader {

    private static final String XML_DIRECTORY = "SQL-XML";

    // 使用 volatile 保证可见性
    private static volatile List<String> ALL_XML_FILES = null;

    // 按目录分组的缓存
    private static volatile Map<String, List<String>> GROUPED_XML_FILES = null;

    // 初始化锁
    private static final ReentrantLock INIT_LOCK = new ReentrantLock();

    // 私有构造器防止实例化
    private SqlXmlLoader() {}

    public static String parserQLXMLByMethodName(String methodName, Map<String, Object> params) {
        // 第一次调用时自动初始化缓存
        List<String> allXmlFiles = getAllXmlFiles();
        if (CollectionUtils.isEmpty(allXmlFiles)) return "";
        try {
            for (String relativePath  : allXmlFiles) {
                // 读取XML文件内容
                String xmlContent = XmlConfigManager.getXmlContent(relativePath );

                // 获取指定ID的SQL内容
                String sqlContent = SqlXmlParser.getSqlContentById(xmlContent, methodName);
                if (StrUtil.isBlank(sqlContent)) continue;

                // 解析SQL语句
                EnhancedSqlProcessor.SqlStatement statement =
                        EnhancedSqlProcessor.parseSqlStatement(methodName, sqlContent);

                // 渲染SQL
                String renderedSql = statement.render(params).trim();
                TraceLog.out(renderedSql);
                return renderedSql;
            }
        } catch (Exception e) {
            log.error("处理失败: " + e);
        }
        throw new RuntimeException("No corresponding SQL statement found");
    }

    /**
     * 获取所有 XML 文件路径（懒加载）
     * @return XML 文件路径列表
     */
    public static List<String> getAllXmlFiles() {
        if (ALL_XML_FILES == null) {
            initializeCache();
        }
        return Collections.unmodifiableList(ALL_XML_FILES);
    }

    // ==================== 私有方法 ====================

    private static void initializeCache() {
        // 双重检查锁定（Double-Checked Locking）
        if (ALL_XML_FILES == null) {
            INIT_LOCK.lock();
            try {
                // 再次检查（防止其他线程已经初始化）
                if (ALL_XML_FILES == null) {
                    // 扫描所有类路径下的 XML 文件
                    List<String> allXmlFiles = scanAllXmlFiles();

                    // 按目录分组缓存
                    Map<String, List<String>> groupedFiles = groupFilesByDirectory(allXmlFiles);

                    // 设置缓存
                    ALL_XML_FILES = Collections.unmodifiableList(allXmlFiles);
                    GROUPED_XML_FILES = Collections.unmodifiableMap(groupedFiles);
                }
            } finally {
                INIT_LOCK.unlock();
            }
        }
    }

    /**
     * 获取资源目录的绝对路径（100% 有效方案）
     */
    private static String getAbsoluteResourcePath() throws IOException {
        // 使用 Spring 的 ClassPathResource 确保获取正确的资源路径
        ClassPathResource classPathResource = new ClassPathResource(XML_DIRECTORY);
        Path resourcePath;

        try {
            // 尝试获取文件系统的实际路径
            File resourceFile = classPathResource.getFile();
            resourcePath = resourceFile.toPath();
        } catch (Exception e) {
            // 当资源在 JAR 内时，使用备用方案
            resourcePath = Paths.get(classPathResource.getURI());
        }

        return resourcePath.toAbsolutePath().toString();
    }

    private static Map<String, List<String>> groupFilesByDirectory(List<String> filePaths) {
        Map<String, List<String>> grouped = new HashMap<>();

        for (String filePath : filePaths) {
            File file = new File(filePath);
            String parentDir = file.getParent();

            if (parentDir != null) {
                String normalizedDir = normalizeDirectory(parentDir);
                grouped.computeIfAbsent(normalizedDir, k -> new CopyOnWriteArrayList<>()).add(filePath);
            }
        }

        return grouped;
    }

    private static String normalizeDirectory(String directory) {
        return directory.replace('\\', '/').toLowerCase();
    }

    // 添加此方法获取真正的源码路径
    public static Path getSourceXmlDir() {
        // 1. 获取项目根目录
        String projectRoot = System.getProperty("user.dir");

        // 2. 构建源码XML目录路径
        Path sourcePath = Paths.get(projectRoot, "src", "main", "resources", "SQL-XML");

        // 3. 验证目录存在性
        if (Files.exists(sourcePath) && Files.isDirectory(sourcePath)) {
            return sourcePath;
        }

        // 4. 后备方案（适用于不同项目结构）
        return Paths.get(projectRoot, "..", "src", "main", "resources", "SQL-XML").normalize();
    }

    // 修改扫描方法 - 返回相对路径
    public static List<String> scanAllXmlFiles() {
        List<String> xmlFiles = new ArrayList<>();
        Path sourceDir = getSourceXmlDir();

        try {
            Files.walk(sourceDir)
                    .filter(Files::isRegularFile)
                    .filter(path -> path.toString().toLowerCase().endsWith(".xml"))
                    .map(sourceDir::relativize) // 获取相对路径
                    .map(Path::toString)
                    .map(path -> path.replace('\\', '/')) // 统一使用正斜杠
                    .forEach(xmlFiles::add);
        } catch (IOException e) {
            log.error("扫描XML文件失败", e);
        }
        return xmlFiles;
    }


}